package org.example.java.util.concurrency.threadlocal;

import java.io.File;
import java.net.MalformedURLException;

/**
 * -Xmx20M  -XX:+PrintGC
 *
 * @author juntao zhang
 * @link http://stackoverflow.com/questions/17968803/threadlocal-memory-leak
 * @date 2015/10/16 13:33
 */
public class ThreadLocalOOM {
  CustomClassLoader cl;

  public ThreadLocalOOM() {
    try {
      cl = new CustomClassLoader(new File("JavaSE/target/classes").toURI().toURL());
    } catch (MalformedURLException e) {
      e.printStackTrace();
    }
  }

  public static void main(String[] args) throws Exception {
    ThreadLocalOOM oom = new ThreadLocalOOM();
    while (true) {
      ThreadLocal<Object> tl = new ThreadLocal<Object>() {
        protected void finalize() {
          System.out.println("ThreadLocal released");
        }
      };
      System.out.println("==begin==");
      //加载器持有加载对象的引用，
      Class<?> clazz = oom.cl.loadClass("org.example.java.util.concurrency.threadlocal.ThreadLocalOOM$Content");
      Object content = clazz.newInstance();
      System.out.println("main:"+content.toString());
      tl.set(content);
      System.out.println("try to release content data");


      tl.set(null);//@1
//      tl.remove();//@2
//    tl = null;//@3
      content = null;//@4

      /////////////////////////////////////////
      //@1 @4 not oom
      //@2 @4 not oom
      //@3 @4 will oom
      /////////////////////////////////////////
      System.out.println("request gc");
      System.gc();
      Thread.sleep(1000);
      System.out.println("==end==");
    }
  }

  public static class Content {
    byte data[] = new byte[1024 * 1024 * 10];

    protected void finalize() {
      System.out.println(this.toString());
      System.out.println("I am released");
    }
  }
}


